/*
 * Author:  Don Koenig
 * Company:  1186 Entertainment
 * Date Modified:  3/13/07
 * Filename:  ClientApplet.java
 */


import java.awt.*;
import java.applet.*;
import java.net.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Date;
import java.lang.Object;
import java.util.*;
import java.lang.Thread.*;
import java.io.*;
import java.net.*;
import java.text.*;


public class ClientApplet extends Applet implements Runnable
{
	enum PanelType{	LOGINPANE, REGISTERPANE, GAMESELECTPANE, LOBBY, ROOM}


	public static String DELIM = "&";
	public JPanel currPane;
	public PanelType currPaneType;
	public BufferedReader fromServer;
	public PrintWriter toServer;
	public int PORT = 33456;
	private Socket sock;
	String serverName;
	private boolean running;

	private String playerName;
	private String loginName;
	private String gameName;

	private char [] inputBuff;

	public void init()
	{
		try
		{
		running = true;
		inputBuff = new char[128];
		try
		{
			serverName = "67.171.65.100";  //I am Don's Desktop IP
			System.out.println("Server name:  " + serverName);

			InetAddress addr = InetAddress.getByName(serverName);

			System.out.println("Connecting...");
			sock = new Socket(addr, PORT);   // Connect to server
			System.out.println("Connected");

			fromServer =
				new BufferedReader(
				new InputStreamReader(
				sock.getInputStream()));   // Get Reader and Writer

			toServer =
				new PrintWriter(
				new BufferedWriter(
				new OutputStreamWriter(sock.getOutputStream())), true);

			Thread outputThread = new Thread(this);  // Thread is to receive strings
			outputThread.setPriority(2);
			outputThread.start();                    // from Server

		}
		catch (Exception e)
		{
			System.out.println("Exception durring initialization:  " + e);
			JOptionPane.showMessageDialog(this,"Error Connecting to Server", "Message", JOptionPane.ERROR_MESSAGE);
		}
		setLayout(new FlowLayout());
		setBounds(0, 0, 800, 600);

		currPaneType = PanelType.LOGINPANE;
		currPane = new Login(this);
		//currPane = new GameSelect(this);
		add(currPane);

	}
	catch (Exception ex) { System.out.println("Exception durring add of Login:  " + ex); }

	}

	public void run()
	{
		System.out.println("Running...");
		while (running)
		{
			try
			{
				String currMsg = fromServer.readLine();
				System.out.println("Received:  "+ currMsg);
				if (currMsg != null)
					processMessage(currMsg);
				else
					running = false;
			}
			catch (Exception e)
			{
				System.out.println("Exception Receiving Message:  " + e);
				running = false;
			}
		}
		System.exit(0);
	}

	public void loadPanel(JPanel pane)
	{
		try
		{
			System.out.println("loadPanel("+pane.getClass().getName()+")");
			this.remove(currPane);
			//this.removeAll();
			currPane = pane;
			this.add(pane);
			currPane.setVisible(true);
			this.setVisible(true);
			repaint();
			this.validate();
		}
		catch (Exception ex) { System.out.println("Exception Loading Panel:  " + ex); }

	}

	public void send(String msg)
	{
		System.out.println("Sending:  " + msg);
		//if (msg.startsWith("1") || msg.startsWith("3"))
		//	loginName = msg.split(DELIM)[1];
		toServer.println(msg);

	}

	public void destroy()
	{
		send("27" + DELIM);
		super.destroy();

	}

	public String getPlayerName()
	{
		return playerName;
	}

	public void logout()
	{
		playerName = null;
		send("8");
		loadPanel(new Login(this));
	}

	/** Extract the data from the received Msg */
	private void processMessage(String msg)
	{
		try
		{
			int type = Integer.parseInt(msg.substring(0, msg.indexOf(DELIM)));
			String[] msgParts;

			switch (type)
			{
				//case 1:		//user Validation 1|username|password
				//	break;
				case 2:		//isValid (user login)  "2DELIMvalid
					try
					{
						if (msg.split(DELIM)[1].equals("valid"))
						{
							//send("4" + DELIM + "0");
							playerName = loginName;
							loginName = null;
							System.out.println("username is valid.  Loading game select");
							loadPanel(new GameSelect(this));
						}
						else
						{
							System.out.println("invalid user login/registration");
							JOptionPane.showMessageDialog(this,"Invalid username/password", "Message", JOptionPane.ERROR_MESSAGE);
						}
					}
					catch (Exception ex) { System.out.println(ex); }
					break;
				//user Registration 3|....
				//Select GameLobby 4|gameID
				case 5:
					msgParts = msg.split(DELIM);
					//String allPlayers1[] = msgParts[1].split(",");
					//String topPlayers1[] = msgParts[2].split(",");
					String allPlayers1[] = msgParts[3].split(",");
					String topPlayers1[] = msgParts[4].split(",");
					ClientApplet ca = this;
					//String lobbyName1 = "Reversi";
					//String playerName1 = "ME!";
					String lobbyName1 = msgParts[1];
					String playerName1 = msgParts[2];
					playerName = playerName1;
					int topScores1[] = { 56, 48, 39, 33, 21 };
					//GameLobby lobby = new GameLobby(ca, lobbyName1, playerName1, allPlayers1, topPlayers1);
					loadPanel(new GameLobby(ca, lobbyName1, playerName1, allPlayers1, topPlayers1));

					//loadPanel(new GameSelect());

					break;

				//#  Request profile information of given user id (view profile)
				//* 6
				//* <String>username

				case 7:	//view profile response  //username gender age rank
					viewProfile(msg);

					break;
				//case 8:		//who put this here?  this isnt right
				//    loadPanel(new Login(this));
				//    break;
				case 9:
					System.out.println("Loading registration");
					loadPanel(new Register(this));
					break;

				case 10:
					System.out.println("Received Challenge");
					if (receiveChallenge(msg))
						send("11" + DELIM + msg.substring(msg.indexOf(DELIM) + 1) + DELIM + "accept");
					else
						send("11" + DELIM + msg.substring(msg.indexOf(DELIM) + 1) + DELIM + "decline");
					JOptionPane challengePane = new JOptionPane("User has challenged you", JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION);
					//JOptionPane.showMessageDialog(this, "Age incorrect.", "Message", JOptionPane.YES_NO_MESSAGE);
					//send #11
					break;
				case 11:		//accept/decline  -- if i receive this, it was a decline, otherwise the msg would be 12
					JOptionPane.showMessageDialog(this, "Challenge Declined", "Message", JOptionPane.ERROR_MESSAGE);
					break;
				case 12:		//start new game
					newGame(msg);
					break;

				case 16: //edit profile

					msgParts = msg.split(DELIM);
					JFrame editProfile = new EditProfile(this, msgParts);
					editProfile.setTitle("Edit Your Profile");
					editProfile.setVisible(true);
					break;
				case 19:
					updatePlayers(msg);
					break;
				case 21:
					updateTopPlayers(msg);
					break;
				case 22:
					try
					{
					((ReversiGameRoom)currPane).board.processMove(msg);
					}
					catch (Exception ex) { System.out.println("Exception processing move:  " + ex); }
					break;
				case 24://receive chat message
					receiveChatMsg(msg);
					break;
				case 25: //receive forfeit message
					((Forfeitable)currPane).receiveForfeit();
					break;
				case 26: //you got kick!!! Kicked! Kicked Kicked Kicked....
					JOptionPane.showMessageDialog(this, "You got kicked!  \nSomeone else logged in with your username.", "Message", JOptionPane.ERROR_MESSAGE);
					loadPanel(new Login(this));
					break;

				default:
					System.out.println("Received illegal message type:  " + type);

			}
		}
		catch (Exception ex)
		{
			System.out.println("Exception Processing Message:  " + ex);
			ex.printStackTrace();
		}
	}

	public void receiveChatMsg(String msg)
	{
		String [] parts = msg.split(DELIM);
		((Chatable)currPane).receiveMsg(parts[1], parts[2]);
	}
	public boolean receiveChallenge(String msg)
	{
		int reply = -1;

		String[] parts = msg.split(DELIM);


		try
		{
			reply = JOptionPane.showConfirmDialog(this, new JLabel("You have been challenged by:  "+parts[1]), "You have been challenged by:  "+parts[1], JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
		}
		catch (Exception ex) { System.out.println(ex); }
		if (reply == JOptionPane.YES_OPTION)
		{
			System.out.println("Accepted");
			return true;
		}
		else
		{
			System.out.println("reply:  " + reply);
			return false;
		}

	}
	public void viewProfile(String msg)
	{
		String [] msgParts = msg.split(DELIM);

		JFrame profile = new JFrame(msgParts[1] + "\'s Profile");
		Container pane = profile.getContentPane();
		pane.setLayout(new BorderLayout());

		JPanel titlePane = new JPanel();
		GridLayout grid = new GridLayout(5, 1);
		grid.setHgap(10);
		grid.setVgap(10);
		JPanel profilePane = new JPanel(grid);


		JLabel title = new JLabel(msgParts[1] + "\'s Profile");
		Font f = new Font("Monospaced", Font.BOLD, 18);
		Font f2 = new Font("SansSerif", Font.PLAIN, 14);
		title.setFont(f);
		//Color c = new Color(0, 200, 0);
		title.setForeground(new Color(131, 25, 38));

		titlePane.add(title);

		JLabel lblName = new JLabel("Username:  " + msgParts[1]);
		JLabel lblEmail = new JLabel("Email:  " + msgParts[5]);
		JLabel lblGender = new JLabel("Gender:  " + msgParts[2]);
		JLabel lblAge = new JLabel("Age:  " + msgParts[3]);
		JLabel lblPoints = new JLabel("Total Points:  " + msgParts[4]);

		lblName.setFont(f2);
		lblEmail.setFont(f2);
		lblGender.setFont(f2);
		lblAge.setFont(f2);
		lblPoints.setFont(f2);

		profilePane.add(lblName);
		profilePane.add(lblEmail);
		profilePane.add(lblGender);
		profilePane.add(lblAge);
		profilePane.add(lblPoints);

		pane.add(titlePane, BorderLayout.NORTH);
		pane.add(profilePane, BorderLayout.CENTER);
		profile.setBounds(0, 0, 250, 300);
		profile.setVisible(true);

	}
	public void newGame(String msg)
	{
		String[] parts = msg.split(DELIM);
		loadPanel(new ReversiGameRoom(this,parts[1],Integer.parseInt(parts[2]),parts[3],Integer.parseInt(parts[4])));
	}

	public void updatePlayers(String msg)
	{
		String[] parts = msg.split(DELIM);
		System.out.println("ClientApplet.updatePlayers:  " + parts[1]);
		String [] players = parts[1].split(",");
		for (int i = 0; i < players.length; i++)
		{
			System.out.println(players[i]);

		}
		try
		{
			((GameLobby)currPane).updatePlayers(players,null);
		}
		catch (Exception ex) { System.out.println("Exception processing updatePlayers msg:  " + ex); }
	}

	public void updateTopPlayers(String msg)
	{
		String[] parts = msg.split(DELIM);
		System.out.println("ClientApplet.updateTopPlayers:  " + parts[1]);
		String [] players = parts[1].split(",");
		for (int i = 0; i < players.length; i++)
		{
			System.out.println(players[i]);

		}
		try
		{
			((GameLobby)currPane).updatePlayers(null,players);
		}
		catch (Exception ex) { System.out.println("Exception processing updateTopPlayers msg:  " + ex); }
	}


	public void close()
	{
		try
		{
			running = false;
			fromServer.close();
			toServer.close();
			sock.close();
		}
		catch (IOException io) { }
	}

	public void showRules(String game)
	{
		URL url = null;
		String url_str = getCodeBase() + game + "_Rules.html";
		try{
			url = new URL(url_str);
		}
		catch(MalformedURLException e){System.out.println("Error in show rules: " + e);}
		System.out.println("Attempting to open: "+url_str);
		getAppletContext().showDocument(url,"_blank");
	}
}
